Model checking with bounded context switches

ABSTRACT

Validity of one or more assertions for any concurrent execution of a plurality of software instructions with at most k−1 context switches can be determined. Validity checking can account for execution of the software instructions in an unbounded stack depth scenario. A finite data domain representation can be used. The software instructions can be represented by a pushdown system. Validity checking can account for thread creation during execution of the plurality of software instructions.

TECHNICAL FIELD

The technical field relates to software modeling, more particularly to modeling of multithreaded software.

BACKGROUND

The design of concurrent programs is a complex endeavor. The main intellectual difficulty of this task lies in reasoning about the interaction between concurrently executing threads. Concurrency results in insidious programming errors that are difficult to reproduce and fix. Therefore, analysis techniques that can automatically detect and pinpoint errors in concurrent programs can be invaluable. Thus, there is a need for static analysis based on model checking for finding subtle safety errors in concurrent programs.

Concurrent programs are significantly more difficult to analyze than sequential programs. For example, the problem of checking assertions in a single-threaded Boolean program with procedures (and consequently an unbounded stack) is decidable. In fact, the algorithm for solving this problem is the basis of a number of efficient static analysis tools for sequential programs. But the problem of checking assertions in a multi-threaded Boolean program with procedures is undecidable.

In the face of this undecidability, most analyses for concurrent programs presented so far have suffered from two limitations. Some analyses restrict the synchronization model, which makes the analysis inapplicable to most common concurrent software applications. A common problem with using abstract data domains, for example, is the threat of false positives (e.g., reports of non-existent bugs). Other analyses are imprecise either because they are flow-insensitive or because they use decidable but coarse abstractions. This limitation makes it extremely difficult to report errors accurately to programmers. As a result, these analyses have seen limited use in checking tools for concurrent software.

Thus, there still remains a need for improved model checking for concurrent software.

SUMMARY

Model checking can proceed with bounded context switches. For example, given a representation of a plurality of software instructions (e.g., a multi-threaded program), the validity of one or more assertions for any concurrent execution of the instructions with at most k−1 context switches can be determined.

A representation (e.g., a model) of a set of software instructions can be received (e.g., by a model checker). For example, a set of software instructions from a multithreaded program can be translated into a form used by a model checker. Translation can include abstraction (e.g., creating a finite data domain representation), such as translating the instructions into a Boolean program. Translation can include constructing a pushdown system representing the software instructions.

Validity determination can include a reachability analysis performed on the representation. The validity determination can account for unbounded stack depth (e.g., to support software using recursion) and dynamic thread creation (e.g., threads created during execution of the software).

The technology can find each invalid assertion (e.g., in light of the context-switch bound). And, the technology can avoid false positives (e.g., reporting that a valid assertion is invalid).

The foregoing and other features and advantages will become more apparent from the following detailed description of disclosed embodiments, which proceeds with reference to the accompanying drawings.

BRIEF DESCRIPTION OF THE FIGURES

FIG. 1 is a block diagram showing an exemplary system for analyzing multithreaded software.

FIG. 2 is a flowchart showing an exemplary method for analyzing multithreaded software, such as with the system shown in FIG. 1.

FIG. 3 is a flowchart showing an exemplary method for analyzing multithreaded software via bounded context switches.

FIG. 4 is a block diagram showing an exemplary model checker for analyzing multithreaded software via bounded context switches.

FIG. 5 is a flowchart showing an exemplary method 400 of providing results that can be performed in conjunction with a model checker, such as the model checker 310 of FIG. 3.

FIG. 6 is a flowchart showing an exemplary method of translating source code into a model. In the example, the model can be a finite state model (e.g., having a finite set of nodes).

FIG. 7 is a flowchart showing an exemplary method for exploring a model of software instructions.

FIG. 8 is a flowchart showing an exemplary method for determining validity of assertions for execution of a set of software instructions.

FIG. 9 is a flowchart showing an exemplary computing environment in which the disclosed technology may be implemented.

DETAILED DESCRIPTION Example 1 Exemplary System for Analyzing Multithreaded Software

FIG. 1 is a block diagram representing an exemplary system 100 for analyzing multithreaded software. In the example, the system takes multithreaded software 110 as input. A model checker 120 analyzes the multithreaded software 110. For example, the model checker 120 can model execution of multithreaded software 110 to detect programming flaws.

In practice, the multithreaded software 110 can be first converted into a model 122, which can represent the multithreaded software 110 in a form appropriate to facilitate modeling.

The model checker 120 can generate results 130. For example, the model checker can indicate whether the multithreaded software 110 contains programming flaws and information about such flaws.

In any of the examples herein, the model checker 120 can be adapted to determine the validity of one or more assertions for any concurrent execution of the multi-threaded software with an upper bound on the number of (e.g., at most k−1) context switches. Thus, the model checker 120 is operable to check validity of assertions for a multi-threaded execution of a multi-threaded program with at most a number of context switches determined based at least in part upon the upper bound. The number k−1 is used in examples herein to facilitate integration with various examples that describe properties holding true for k contexts (e.g., the uninterrupted sequence of actions by a single thread between context switches). However, any positive integer n (e.g., 2 or more) can be chosen for use with the technology.

Also, although a fixed number of threads (e.g., 2 or more) can be used, the model checker can account for dynamic thread creation (e.g., creation of threads during execution of the multi-threaded software).

Example 2 Exemplary Method for Analyzing Multithreaded Software

FIG. 2 is a flowchart showing an exemplary method 200 for analyzing multithreaded software, such as with the system 100 shown in FIG. 1. The methods of any of the examples described herein can be performed in software executing computer-executable instructions. Such instructions can be stored in one or more computer-readable media.

At 210, a model of multithreaded software is built. In any of the examples herein, building the model can include constructing a finite data domain representation of the software. In any of the examples herein, building the model can include constructing a pushdown system representation of the software (e.g., a pushdown model based on the finite data domain representation).

At 212, the model can be checked for programming flaws. For example, execution of the software can be modeled to detect whether any specified invariants (e.g., asserts) fail for any execution path of the software. In any of the examples described herein, the number of context switches for the execution path of the software can be bounded.

In practice, building the model and checking for programming flaws can be combined into a single process. For example, the model can be built as the model for the multithreaded software is checked for programming flaws.

Example 3 Exemplary Method for Analyzing Multithreaded Software with Bounded Context Switches

FIG. 3 is a flowchart showing an exemplary method 300 for analyzing multithreaded software via bounded context switches. At 310, a representation of software instructions (e.g., a multi-threaded program) is received. The representation may be created as part of the method 300. Alternatively, the representation may be created external to the method 300.

At 312, validity is determined for one or more assertions for any concurrent execution of the software instructions with at most k−1 context switches. For example, execution of the software can be modeled to detect whether any specified invariants (e.g., asserts) fail for any execution path of the software. The validity determination can account for unbounded stack depth. The validity determination can also be performed for dynamic thread creation (e.g., threads created during execution of the software being modeled).

Example 4 Exemplary Software to be Tested

In any of the examples herein, software to be tested can take the form of source code, from which a model of the software can be generated automatically by the testing system. For example, the modeled software can take the form of source code of languages such as C, C++, the VISUAL BASIC programming language of Microsoft Corporation, the JAVA language of Sun Microsystems, Inc., and related or other languages.

If desired, the source language can be translated into an intermediate form (e.g., an intermediary source-like language), from which the software model is generated. In this way, any number of source languages can be supported by first translating them into the intermediate form.

During construction of a model representing the source language, a finite data domain representation can be generated. Further, a pushdown system representing the source (e.g., a pushdown system representing a finite data domain version of the source) can be generated.

The system can support a wide variety of software to be tested. For example, the modeled software to be tested can include concurrent programs, such as multithreaded programs. Although concurrency is commonly used in web services and workflows, the techniques described herein can also be applied to any other (e.g., operating system, device driver, and the like) software.

Example 5 Exemplary Multithreaded Software

Exemplary multithreaded software includes software that makes use of more than one thread during execution of the software. For example, multithreaded software can include a scenario where two threads access one or more shared variables. Such software can include synchronization mechanisms (e.g., locks, mutexes, semaphores and the like) to avoid undesirable phenomena such as race conditions for shared variables or other conditions associated with execution of concurrent programs. Whenever multiple threads are present, various types of interleavings between threads is possible, and the exact order of execution is generally indeterminable beforehand. There exists a potentially exponential number of ways interleavings can take place. In practice, two or more threads may be executing different (e.g., separate) code.

Example 6 Exemplary Context Switching

A context switch refers to the phenomenon of switching execution from one thread to another. Thus, as used herein, a context generally refers to an uninterrupted sequence of actions by a single thread (e.g., between context switches). Thus, in an execution with k contexts, execution switches from one thread to another k−1 times.

In any of the examples herein, the value for k can be greater than one (i.e., k−1 is greater than zero). k may take any (e.g., positive) representable value; therefore, an arbitrary upper bound on the number of context switches can be specified. In any of the examples herein, the value for k or k−1 can be configured if desired. For example, the value can be input by a user or set as a constant. In any of the examples herein, it may be desirable to use some other notation to represent the number of context switches (e.g., n).

Example 7 Exemplary Unbounded Stack Depth

A difficulty with context bounded model checking is that in each thread context, an unbounded number of stack configurations could be reachable due to recursion. Since a context switch may happen at any time, a precise analysis needs to account for scheduling other threads from any of these configurations. To guarantee termination, a systematic state exploration algorithm can use a finite representation of an unbounded set of stack configurations. Previous algorithms based on transactions and procedure summaries are not guaranteed to terminate for context-bounded model checking because they keep an explicit representation of the stack of each thread.

Example 8 Exemplary Model Checker

FIG. 4 is a block diagram showing an exemplary model checker 410 for analyzing multithreaded software via bounded context switches. A model checker generally explores the possible ways (e.g., all possible ways or a relevant subset thereof) of executing a system. In the example, the model checker 410 receives a model 420 of multithreaded software. A context-switches bound 430 (e.g., a limit on the number of context switches allowed during modeling) is applied to the model 420 during processing. The model checker 410 can search through various interleavings for concurrent execution of the software represented by the model, but will find only those assertion violations that occur within the number of context switches as indicated by the context-switches bound. If an assertion fails within the number of context switches, the model checker will find it. Further, the model checker can be constructed such that every assertion reported as failed is failed (e.g., it is not a false positive).

Example 9 Exemplary Abstraction

In any of the examples herein, various abstraction techniques can be applied when generating a representation of software instructions. For example, a finite data domain representation of the software instructions can be created.

In practice, certain calculations (e.g., as part of if-then statements) can be ignored, and a generic non-determinative function substituted in its place.

Abstraction can also include creating a pushdown system that represents the software instructions. The pushdown system can be based on the finite data domain representation of the software.

Example 10 Exemplary Results Reporting

FIG. 5 shows an exemplary method 500 for reporting results that can be performed in conjunction with a model checker, such as the model checker 410 of FIG. 4.

At 510, source code is received (e.g., by model checker 410 of FIG. 4).

At 512, source code is translated into a model (e.g., a pushdown system) using an input language for a model checker. In some instances, the model checker can perform the translation. In other instances, the translation can be performed external to the model checker.

At 514, the model checker explores the model looking for bugs (e.g., failed assertions). A bound (e.g., a limit on the number of context switches allowed) may be set.

At 516, results from the exploration may be provided as output (e.g., to a programmer). Results can include an error trace (e.g., a stepwise series of executions that lead to a bug).

Example 11 Exemplary Source Code Translation

FIG. 6 shows an exemplary method 600 for translating source code into a model.

At 610, source code (e.g., software instructions) is provided as input.

At 612, the source code is translated into a model (e.g., to be used in conjunction with a model checker to identify possible programming flaws within the source code). For example, the source code can be translated into a model that can be explored with an upper bound on the number of context switches.

Example 12 Exemplary Model Exploration

FIG. 7 shows an exemplary method 700 for exploring a model of software instructions.

At 710, a model of software instructions is received.

At 712, the model is explored with a model checker to seek and identify possible programming flaws within the software instructions. A bound can be set on the number of context switches during concurrent execution of the software modeled.

Example 13 Exemplary Determination of Validity of Assertions

FIG. 8 is a flowchart showing an exemplary method for determining validity of assertions for execution of a set of software instructions.

At 810, a model of a set of concurrent software instructions (e.g., a multi-threaded program) is received.

At 812, a limit to the number of context switches to be allowed is set. The limit will be applied during analysis of the model. The limit may be an arbitrary value or otherwise determined.

At 814, the validity of one or more assertions for concurrent execution of the concurrent software instructions (e.g., with at most the number of context switches set) is determined as part of the analysis.

Example 14 Exemplary Reachability

A thread can be represented by a stack machine. Reachability for a stack machine (e.g., a thread) with a finite data domain is generally decidable. This is usually because it can be represented by something that is finite (e.g., a finite state machine). Reachability for a stack machine with an infinite data domain is generally undecidable. In the example, data domains can be abstracted to facilitate the use of a finite data domain in a situation that would otherwise require an infinite data domain. For example, a finite state machine can represent a set of reachable configurations of a pushdown system.

Example 15 Exemplary Advantage: Finding Failed Assertions

In any of the examples described herein, a constant number (e.g., k) can be chosen for use with the technology to determine whether an assertion will fail for any concurrent execution involving k−1 context switches. Thus, there could be a concurrent execution that does result in a failed assertion (e.g., on the k^(th) context switch).

However, in a great many cases, an assertion will fail within a relatively small number of k. For example, although k bounds the number of context switches, it does not bound the number of instructions that a thread might execute between context switches. Thus, an exceedingly long error trace may result in finding a failed assertion, even if there are only a relatively small number of context switches.

Accordingly, in practice, the technology can have great value for software verification purposes.

Example 16 Exemplary Pushdown Systems

In any of examples described herein, software can be modeled via a pushdown system. Whether an assertion fails can be determined via a reachability analysis. Due to the properties of pushdown systems, it can be shown that determining whether an assertion fails within a bounded number of context switches for a finite data domain is decidable, even with unbounded stack depth. Thus, the analysis can account for programs using recursion.

Further, it can be shown that the model checking can be constructed so that no false positives are found (e.g., every assertion identified as invalid is invalid). Further, it can be shown that the model checking can account for dynamic thread creation (e.g., creation of threads during execution of the software being modeled). Each thread can be represented by a pushdown system.

Example 17 Exemplary Determination of Reachability

An interprocedural static analysis on a concurrent program defines a k-bounded transition relation; defines at least one aggregate configuration based at least in part upon the k-bounded transition relation; defines at least one transition relation based at least in part upon the aggregate configuration; and determines, via the above three, whether at least one execution path within a configuration of a concurrent pushdown system is reachable.

In the example, the configuration of the concurrent pushdown system can be determined to be reachable if c_(in), →*_(p)c, wherein c_(in) represents an initial configuration of the concurrent pushdown system and c represents the configuration of the concurrent pushdown system.

In the example, the configuration can be deemed to be k-reachable if

wherein c_(in) represents an initial configuration of the concurrent pushdown system, c represents the configuration of the concurrent pushdown system, and K represents the k-bounded transition relation.

Example 18 Exemplary Thread Representation

In any of the examples described herein, a thread can be represented by a pushdown system. Additionally, multiple threads can be represented by multiple pushdown systems, respective threads being represented by a corresponding pushdown system.

Example 19 Exemplary Sample Code Having Subtle Bugs Caused by Concurrency

This example demonstrates how subtle bugs caused by concurrency can be manifested by executions with few contexts. Table 1 shows code that is typically found in certain device drivers for handling asynchronous Interrupt Request Packet (IRP) cancellation. TABLE 1 Sample Code NTSTATUS DispatchRoutine( DEVICE_OBJECT *obj, IRP *irp) { DEVICE_EXTENSION *e = obj−>DeviceExtension; . . . IoSetCancelRoutine (irp, CancelRoutine); KeAcquireSpinLock(&e−>SpinLock); EnqueueIrp(irp); KeReleaseSpinLock(&e−>SpinLock); IoMarkIrpPending(irp); return STATUS_PENDING; } void CancelRoutine( DEVICE_OBJECT *obj, IRP *irp) { DEVICE_EXTENSION *e = obj−>DeviceExtension; IoReleaseCancelSpinLock( ); . . . KeAcquireSpinLock(&e−>SpinLock); DequeueIrp(irp); KeReleaseSpinLock(&e−>SpinLock); IoCompleteIrp(irp); } void IoCancelIrp(IRP *irp) { DEVICE_OBJECT *obj; void (*Routine) (IRP *); IoAcquireCancelSpinLock( ); . . . Routine = IoSetCancelRoutine(irp, NULL); if (Routine != NULL) { Routine(irp); } }

DispatchRoutine is a typical dispatch function of a device driver. The code for this function shows that a decision has been made to enqueue irp for future processing. First, the function IoSetCancelRoutine is called to set a cancellation routine for irp. The cancellation routine is called by the operating system if irp is cancelled. Then, irp is enqueued into a device queue under the protection of a spin lock. Finally, irp is marked pending and STATUS_PENDING is returned. While a thread is processing irp in DispatchRoutine, the operating system may cancel irp asynchronously by calling the function IoCancelIrp in another thread. This thread calls the cancel routine for irp if it is non-null.

Consider the following execution. The first thread begins by calling DispatchRoutine(obj, irp), sets the cancellation routine for irp to CancelRoutine, and proceeds until the call to IoMarkIrpPending(irp). Just before this call, a context switch occurs and IoCancelIrp (obj, irp) begins execution in a second thread. This thread calls CancelRoutine(obj, irp), which eventually calls IoCompleteIrp(irp). A second context switch occurs and the first thread calls IoMarkIrpPending(irp), thereby violating the following important rule governing the interface between the driver and the operating system.

An IRP should not be marked pending after it has been completed.

Note that the erroneous execution had only three contexts (and two context switches). Additional experimental evidence for the belief that many errors manifest within a small number of contexts is provided by previous work with an existing static checker, where a variety of errors could be found in low-level systems code similar to the one shown above.

Example 20 Exemplary Pushdown Systems

Referring to Table 2, let G and Γ be arbitrary fixed finite sets. One should refer to G as the set of global states and refer to Γ as the stack alphabet. One should let g range over elements of G and let γ range over elements of Γ. A stack w is an element of Γ*, the set of finite strings over Γ, including the empty string ε. A configuration c is an element of G×Γ*; configurations can be written as c=

g, w

with gεG and wεΓ*. TABLE 2 Domains γ ∈ Γ Stack alphabet w ∈ Γ* Stack g ∈ G Global state Δ ⊂ (G × Γ) × (G × Γ*) Transition relation c ∈ G × Γ* Configuration →Δ ⊂ (G × Γ*) × (G × Γ) Pds transition

A transition relation Δ over G and Γis a finite subset of (G×Γ)×(G×Γ*). A pushdown system P=(G, Γ, Δ, g_(in), w_(in)) is given by G, Γ, a transition relation Δover G and Γ, and an initial configuration

g_(in), w_(in)

. The transition relation Δ determines a transition system on configurations, denoted →_(Δ) as follows:

g, γw′

→_(Δ)

g′, ww′

for all w′εΓ*, if and only if (

g, γ

,

g′, w

)εΔ. →*_(Δ) is written to denote the reflexive, transitive closure of →_(Δ). Notice that, by the signature of Δ, there are no transitions →_(Δ) from a configuration whose stack is empty. Hence, a pushdown system as defined here halts when the stack becomes empty.

A configuration c of a pushdown system is generally called reachable if and only if c_(in), →*_(Δ)c, where c_(in), is the initial configuration of the pushdown system. In general, there can be infinitely many reachable configurations of a pushdown system, because the stack is unbounded.

The reachability problem for pushdown systems is decidable because the set of reachable configurations (sometimes called the pushdown store language) of a pushdown system is regular. A regular pushdown store automaton A=(Q, Γ, δ, I, F) is a finite automaton with states Q, alphabet Γ, transition relation δ⊂Q×Γ×Q, initial states I and final states F. The automaton may contain ε-transitions. The sets Q and I satisfy G⊂Q and I⊂G. Such an automaton defines a language of pushdown configurations by the following rule:

-   -   A accepts a pushdown configuration         g, w         , if and only if A accepts the word w when started in the state         g.

A subset S⊂G×Γ* of pushdown configurations is generally called regular if and only if there exists a regular pushdown store automaton A such that S=L(A).

For a pushdown system P=(G, Γ, Δ, g_(in), w_(in)) and a set of configurations S⊂G×Γ*, let Post*_(Δ)(S) be the set of states reachable from S, i.e., Post*_(Δ)(S)={c|∃c′εS. c′→*_(Δ)c}. The following theorem shows that the set of reachable configurations from a regular set of configurations is again regular:

-   -   Theorem 1: Let P=(G, Γ, Δ, g_(in), w_(in)) be a pushdown system,         and let A be a regular pushdown store automaton. There exists a         regular pushdown store automaton A′ such that         Post*_(Δ)(L(A))=L(A′). The automaton A′ can be constructed from         P and A in time polynomial in the size of P and A.

The construction of A′ from A can be done by adding states and transitions to A. Let g, g′ range over G and let q range over Q. For every pair (g′, γ′) such that Δ contains a transition (

g, γ

,

g′, γ′, γ″

) a new state q_(g′, γ′) is added. Three kinds of transitions are successively added. First, a transition (g′, ε, q) is added whenever (

g, γ

,

g′, ε

)εΔand qεδ*(g, γ). Second, if (

g, γ

,

g′, γ′

)εΔ and qεδ*(g, γ) then transition (g′, γ′, q) is added. Third, if (

g, γ

,

g′, γ′, γ′

)εΔ and qεδ*(g, γ) then transitions (g′, γ′, q_(g′, γ′)) and (q_(g′, γ′), γ″, q) are added.

Example 21 Exemplary Concurrent Pushdown Systems

A concurrent pushdown system is a tuple P=(G, Γ, Δ₀, . . . , Δ_(N), g_(in), w_(in)) with transition relations Δ₀, . . . , Δ_(N) over G and Γ, N≧0, an initial state g_(in) and an initial stack w_(in). A configuration of a concurrent pushdown system is a tuple c=

g, w₀, . . . , w_(N)

with gεG and w_(i)εΓ*, that is, a global state g followed by a sequence of stacks w_(i), one for each constituent transition relation. The initial configuration of P is (g_(in), w_(in), . . . , w_(in)) where all N+1 stacks are initialized to w_(in). The transition system of P, denoted →p, rewrites configurations of P by rewriting the global state together with any one of the stacks, according to the transition relations of the constituent pushdown systems.

Formally,

g, w₀, . . . , w_(i), . . . w_(N)

→_(i)

g′, w₀, . . . , w′_(i), . . . w_(N)

is defined if and only if

g, w_(i)

→_(Δi)

g′, w′_(i)

The transition relation →p is defined on configurations of P by the union of the →_(i), i.e., →p=∪_(i=0) ^(N)→_(i). TABLE 3 Concurrent Pushdown System boolean m = 0, task = 0; Thread 0 Thread 1 while(1) { while(1) { L1: wait(

m); L4: wait(m); L2: InitTask( ); L5: DoTask( ); L3: m := 1; L6: m := 0; } } InitTask( ) { DoTask( ) { L7: task := {0,1}; L8: task :=

task; } }

To illustrate how a concurrent pushdown system can be used to represent programs, a simple program with two threads is shown in Table 3. This program is represented as a concurrent pushdown system P=(G, Γ, Δ₀, Δ₁, g_(in), w_(in)). One should let G be the set of valuations to global variables m and task. There is a special local variable pc, the program counter, which takes values from the set of program labels PC={L0, L1, L2, . . . , L8}. L0 is a special label not present in the program used to initialize the stack of each thread. One should let Γ be the set of valuations to pc. One should write (m, task) to denote the valuation assigning the value m to m and the value task to task. Hence, a transition (

g, γ

,

g′, w

) has the form (

(m, task), pc

,

(m′, task′), w

) where wεPC*.

The initial global state g_(in)=(0, 0). The initial stack configuration w_(in)=L0. Two initial transitions, (I0) and (I1), are introduced for Δ₀ and Δ₁, respectively. (I0) (

(0, 0), L0

), (

(0, 0), L1

) (I1) (

(0, 0), L0

,

(0, 0), L4

) Thread 0 and thread 1 use transitions (I0) and (I1) to move to their first instructions respectively.

The remainder of the transitions in Δ₀ are shown below. (

(0, task), L1

,

(0, task), L2

)   (1) (

(m, task), L2

,

(m, task), L7·L3

)   (2) (

(m, task), L3

,

(1, task), L1

)   (3) (

(m, task), L7

,

(m, 0), ε

)   (4) (

(m, task), L7

,

(m, 1), ε

)   (5)

A compact notation has been used in describing the transitions above. Each of (1) through (5) denotes a set of transitions for each value of m and task, where m and task range over the set {0, 1}.

The transition relation Δ₁ for thread 1 can be defined analogously.

Example 22 Exemplary Bounded Reachability

A configuration c is generally called reachable if and only if c_(in), →*_(p)c, where c_(in) is the initial configuration. The reachability problem for concurrent pushdown systems is undecidable. However, bounding the number of context switches allowed in a transition generally leads to a decidable restriction of the reachability problem. For a positive natural number k, the k-bounded transition relation is defined as

on configurations c inductively, as follows:

iff ∃i. c→*_(i)c′

iff there exists c″ and i such that

Thus, a k-bounded transition contains at most k−1“context switches” in which a new relation →_(i) can he chosen. Notice that the full transitive closure of each transition relation →_(i) applied within each context. It can be said that a configuration c is k-reachable if

The k-bounded reachability problem for a concurrent pushdown system P is:

Given configurations to c₀ and c₁, is it the case that

Example 23 Exemplary Aggregate Configurations

For a fixed k, the lengths and state spaces of k-bounded transition sequences may be unbounded, since each constituent transition relation →*_(i) may generate infinitely many transitions containing infinitely many distinct configurations. Therefore, decidability of k-bounded reachability requires an argument. In order to formulate this argument, a transition relation is defined over aggregate configurations of the form

g, R₀, . . . , R_(N)

, where R_(i) are regular subsets of Γ*.

For a global state gεG and a regular subset R⊂Γ*, one should let

g, R

denote the following set of configurations:

g, R

={

g, w

|wεR} Notice that

g, 0

=0. For G={g₁, . . . , g_(m)}, any regular set of configurations S⊂G×Γ*, can be written as a disjoint union $\begin{matrix} {S = {\underset{i = 1}{\overset{m}{\uplus}}\left\langle \left\langle {g_{i},R_{i}} \right\rangle \right\rangle}} & (1) \end{matrix}$ for some regular sets of stacks R_(i) ⊂Γ*, i=1 . . . m (if there is no configuration with global state g_(j) in S, then we take R_(j)=0.) By Theorem 1, the set Post*_(Δ)(S) for regular S can also be written in the form (1), since it is a regular set. One can denote that

g′, R′

is a component of the set Post*_(Δ)(S) as represented in the form (1), writing

g′, R′

εPost*_(Δ)(S) if and only if Post*_(Δ)(S)=

_(i=1) ^(m)

g_(i), R_(i)

with

g′, R′

=

g_(j), R_(j)

for some jε{1, . . . , m}.

Given a concurrent pushdown system P=(G, Γ, Δ₀, . . . , Δ_(N), g_(in), w_(in)) one can define relations

on aggregate configurations, for i=0 . . . N, by:

g, R₀, . . . , R_(i), . . . R_(N)

g′, R₀, . . . , R′_(i), . . . , R_(N)

if and only if

g′, R′_(i)

εPost*_(Δ) _(i) (

g, R_(i)

).

Finally, one can define the transition relation

on aggregate configurations by the union of the

i.e.,

=(∪_(i=0) ^(N)

). For aggregate configurations a₁ and a₂, one can write a₁

a₂ if and only if there exists a transition sequence using starting at a₁ and ending at a₂ with at most k transitions. Notice that each relation

_(i) contains the full transitive closure computed by the Post*_(Δ) _(i) operator.

The following theorem reduces k-bounded reachability in a concurrent pushdown system to repeated applications of the sequential Post* operator:

-   -   Theorem 2: Let a concurrent pushdown system P=(G, Γ, Δ₀, . . . ,         Δ_(N), g_(in), w_(in)) be given. Then, for any k,         g, w₀, . . . , w_(N)         g′, w′₀, . . . , w′_(N)         if and only if         g, {w₀}, . . . , {w_(N)}         g′, R′₀, . . . , R′_(N)         for some R′₀, . . . , R′_(N) such that w′_(i)εR′_(i) for all         iε{0, . . . , N}.

Example 24 Exemplary Algorithm

Theorem 1 and Theorem 2, described above, together give rise to an algorithm for solving the context-bounded reachability problem for concurrent pushdown systems. The algorithm is shown in Table 4. TABLE 4 Algorithm Input: Concurrent pushdown system (G, Γ, Δ₀,..., Δ_(N), g_(in), w_(in)) and bound k 0. let A_(in) = (Q, Γ, δ, {g_(in)}, F) such that L(A_(in)) = {<g_(in), w_(in)>}; 1. WL := {(<g, A_(in), . . . , A_(in)>,0)}; //There are N copies of A_(in). 2. Reach := {<g, A_(in), . . . , A_(in)>); 3. while (WL not empty) 4. let (<g, A₀,..., A_(N)>, i) = REM0VE(WL) in 5. if (i < k) 6. forall (j = 0...N) 7. let A′_(j) = Post*_(Δ) _(j) (A_(j)) in 8. forall (g′ ∈ G(A′_(j))) { 9. ADD(WL,(<g′, RENAME(A₀, g′),..., AN0NYMIZE(A′_(j), g′),..., RENAME(A_(N), g′)>, i + 1)); 10. Reach := Reach ∪ {<g′, RENAME(A₀, g′),..., AN0NYMIZE(A′_(j), g′),..., RENAME(A_(N) } Output : Reach

The algorithm processes a worklist WL containing a set of items of the form (

g, A₀, . . . , A_(N)

, i), where gεG is a global state, the A_(j) are pushdown store automata, and i is an index in the range {0, . . . , k−1}. The operation REMOVE(WL) removes an item from the worklist and returns the item; ADD(WL, item) adds the item to the worklist. The initial pushdown store automaton A_(in)=(Q, Γ, δ, {g_(in)}, F) has initial state g_(in) and accepts exactly the initial configuration (g_(in), w_(in)). In the line numbered 6 of the algorithm in Table 4, the pushdown store automaton A′_(j)=Post*_(Δ) _(i) (A_(j)) is understood to be constructed according to Theorem 1 so that L(A′_(j))=Post*_(Δ) _(i) (L(A_(j))). In line 8, G(A′_(j))={g′|∃w.

g′, w

εL(A′_(j))}. All pushdown store automata A_(j) constructed by the algorithm have at most one start state gεG. When applied to such an automaton RENAME(A, g′) returns the result of renaming the start state if any of A to g′. The operation ANONYMIZE(A, g′) is obtained from A by renaming all states of A except g′ to fresh states that are not in G.

The algorithm in Table 4 works by repeatedly applying the Post* operator to regular pushdown store automata that represent components in aggregate configurations. The operations RENAME and ANONYMIZE are necessary for applying Theorem 1 repeatedly, since the construction of pushdown store automata uses elements of G as states in these automata. In order to avoid confusion between such states across iterated applications of Theorem 1, renaming of states from G is necessary. Because of this renaming, successive pushdown store automata constructed by the algorithm in Table 4 may grow for increasing values of the bound k. The fact that the pushdown store automata could grow unboundedly for ever increasing k underlies the undecidability of the unbounded reachability problem.

-   -   Theorem 3 Let a concurrent pushdown system P=(G, Γ, Δ₀, . . . ,         Δ_(N), g_(in), w_(in)) be given. For any k, the algorithm in         Table 4 terminates on input P and k, and         g_(in), {w_(in)}, . . . , {w_(in)}         g′, R′₀, . . . , R′_(N)         if and only if the algorithm outputs Reach with         g′, A′₀, . . . , A′_(N)         εReach such that and L(A′_(i))         g′, R′_(i)         for all iε{0, . . . , N}.

Termination of the algorithm follows from the fact that the ADD statement in line 9 can only be executed a bounded number of times. One should let Count(i) denote the number of times ADD is called in line 9 with index argument i. Then, Count(0)=1 and Count(i+1)=N×|G|×Count(i), since the loops in line 6 and 8 a-re bounded by N and |G|, respectively. Hence, Count(i+1)≦(N×|G|)^(i) is hounded for all i. Since an item is removed in each iteration of the while loop at line 4, it follows that the worklist eventually becomes empty and the algorithm terminates.

The algorithm computes reachability for the given pushdown system with k-bounded contexts by computing the reachability relation

over aggregate configurations represented by pushdown store automata. Reachable aggregate configurations (g′, R′₀, . . . , R′_(N)) are represented by pushdown store automata in the worklist items by the vectors (g, A′₀, . . . , A′_(N)) and are collected in the set Reach. The theorem follows from Theorem 1, which implies that the automata constructed in line 7 of the algorithm correctly represent components of aggregate configurations.

Theorem 2 together with Theorem 3, described above, together imply that the algorithm in Table 4 solves the context-bounded model-checking problem, since Theorem 2 shows that aggregate configurations correctly represent reachability in the relation

.

For a concurrent pushdown system P=(G, Γ, Δ₀, . . . , Δ_(N), g_(in), w_(in)), one can measure the size of P by |P|=max(|G|, |Δ|, |Γ|). For a pushdown store automaton A=(Q, Γ, δ, I, F), one can measure the size of A by |A|=max(|Q|, |δ|, |Γ|).

-   -   Theorem 4 For a concurrent pushdown system P=(G, Γ, Δ₀, . . . ,         Δ_(N), g_(in), w_(in)) and a bound k, the algorithm in FIG. 3         decides the k-bounded reachability problem in time         O(k³(N|G|)^(k)|P|⁵).         The Post* operation on a set represented by A can be computed in         time O(|P|²|A|+|P|³). One should let A(i) denote the size of         automaton A as extended by successive applications of the Post*         operator throughout the iterations of the algorithm. It can be         seen that A(i)≦c+i|P|×i|P|×|P|=O(i²|P|³), where the terms i|P|         come from the number of states of the automaton, and |P| bounds         the number of labeled edges in its transition relation.         Therefore, the time to compute Post* at index i is bounded by         Cost(i)==O(|P|²×i²|P|³+|P|³)=O(i²|P|⁵). With Items(i) denoting         the number of work items with index i created throughout a run         of the algorithm, one has Items(0)=1 and         Items(i+1)=N|G|×Items(i)=(N|G|)^(i). Summing over i=1 . . . k         iterations, the total cost of the algorithm is dominated by         Σ_(i=1) ^(k)(N|G|)^(i)×Cost(i)=O(k³(N|G|)^(k)|P|⁵).

Example 25 Exemplary Dynamic Concurrent Pushdown Systems

In the example, a dynamic concurrent pushdown system is defined with operations for forking and joining on a thread. To allow for dynamic fork join parallelism, program variables in which thread identifiers can be stored are allowed. Thread identifiers are members of the set Tid={0, 1, 2, . . . }. The identifier of a forked thread may be stored by the parent thread in such a variable. Later, the parent thread may perform a join on the thread identifier contained in that variable.

Formally, a dynamic concurrent pushdown system is a tuple (GBV, GTV, LBV, LTV, Δ, Δ_(F), Δ_(J), g_(in), γ_(in)).

The various components of this tuple are described below.

-   -   GBV is the set of global variables containing Boolean values and         GTV is the set of global variable containing thread identifiers.         Let G be the (infinite) set of all valuations to the global         variables.     -   LBV is the set of local variables containing Boolean values and         LTV is the set of local variables containing thread identifiers.         Let F be the (infinite) set of all valuations to the local         variables.     -   Δ⊂(G×Γ)×(G×Γ*) is the transition relation describing a single         step of any thread.     -   Δ_(F) ⊂Tid×(G×Γ)×(G×Γ*) is the fork transition relation. If (t,         g, γ         ,         g′, w         )εΓ_(F), then in the global store g a thread with γ at the top         of its stack may fork a thread with identifier t modifying the         global store to g′ and replacing γ at the top of the stack with         w.     -   Δ_(J) ⊂LTV×(G×Γ)×(G×Γ*) is the join transition relation. If (x,         g, γ         ,         g′, w         )εΔ_(J), then in the global store g a thread with γ at the top         of its stack blocks until the thread with identifier γ(x)         finishes execution. On getting unblocked, this thread modifies         the global store to g′ and replaces γ at the top of the stack         with w.     -   g_(in) is a fixed valuation to the set of global variables such         that g_(in)(x)=0 for all xεGTV.

γ_(in) is a fixed valuation to the set of local variables such that γ_(in)(x)=0 for all xεLTV. TABLE 5 Domains ss ∈ Stacks = Tid → (Γ ∪ {$})* c ∈ C = G × Tid × Stacks Configuration

∈ C × C

Every dynamic concurrent pushdown system is equipped with a special symbol $∉Γ to mark the bottom of the stack of each thread. A configuration of the system is a triple (g, n, ss), where g is the global state, n is the identifier of the last thread to be forked, and ss(t) is the stack for thread tεTid. The execution of the dynamic concurrent pushdown system starts in the configuration

g_(in), 0, ss₀

, where ss(t)=γ_(in)$ for all tεTid. The rules shown below define the transitions that may be performed by thread t from a configuration

g, n, ss

. TABLE 6 Operational Semantics (SEQ) t ≤ n ⁢   ⁢ ss ⁡ ( t ) = γw ′ ( 〈 g , γ 〉 , 〈 g ′ ⁢   , w 〉 ) ⁢   ⁢ ε ⁢   ⁢ Δ 〈 g , n , ss 〉 ⁢   ⁢ ⁢ t ⁢   ⁢ 〈 g ′ , n , ss ⁡ [ t := ww ′ ] 〉 (SEQEND) t ≤ n ⁢   ⁢ ss ⁡ ( t ) = $ 〈 g , n , ss 〉 ⁢   ⁢ t ⁢   ⁢ 〈 g , n , ss ⁡ [ t := ε ] 〉 (FORK) t ≤ n ⁢   ⁢ ss ⁡ ( t ) = γw ′ ( n + 1 , 〈 g , γ 〉 , 〈 g ′ ⁢   , w 〉 ) ⁢   ⁢ ε ⁢   ⁢ Δ F 〈 g , n , ss 〉 ⁢   ⁢ t ⁢   ⁢ 〈 g ′ , n + 1 , ss ⁢   [ t := ww ′ ] 〉 (JOIN) t ≤ n ⁢   ⁢ ss ⁡ ( t ) = γw ′ ⁢   ⁢ x ⁢   ⁢ ε ⁢   ⁢ LTV ( x , 〈 g , γ 〉 , 〈 g ′ ⁢   , w 〉 ) ⁢   ⁢ ε ⁢   ⁢ Δ J ⁢   ⁢ ss ⁡ ( γ ⁡ ( x ) ) = ε 〈 g , n , ss 〉 ⁢   ⁢ t ⁢   ⁢ 〈 g ′ , n , ss ⁢   [ t := ww ′ ] 〉

In the example, all rules are guarded by the condition t≦n indicating that thread t must have already been forked. Thus, only thread 0 can make a move from the initial configuration (g_(in), 0, ss₀). The rule (SEQ) allows thread t to perform a transition according to the transition relation Δ. The rule (SEQEND) is enabled if the top (and the only) symbol on the stack of thread t is $. The transition pops the $ symbol from the stack of thread t without changing the global state so that thread t does not perform anymore transitions. The rule (FORK) creates a new thread with identifier n+1. The rule (JOIN) is enabled if thread γ(x), where γ is the symbol at the top of the stack of thread t, has terminated. The termination of a thread is indicated by an empty stack. TABLE 7 Example Dynamic Thread Creation boolean task = 0; Thread 0 Tid t; while(1) { L1: InitTask( ); L2: t:= async DoTask( ); L3: join(t); } InitTask( ) { DoTask( ) { L7: task := {0, 1}; L8: task :=

task; }

Table 7 shows an example of dynamic thread creation. This example replaces the mutex-based synchronization of the example in Table 2 with fork join synchronization. To model dynamic thread creation, introduce a (ghost) global variable inpc is introduced which takes values from the set PC. This variable contains the program label of a thread when it is forked. This program is represented as a dynamic concurrent pushdown system: ({task, inpc}, 0, {p}, {t}, Δ, Δ_(F), Δ_(J), g_(in), γ_(in)). The initial global state g_(in)=(0, L1). The initial stack configuration w_(in)=(0, L0). An initial transition (I) is introduced in Δ: (I) (

(task, inpc), (0, L0)

,

(task, L0), (0, inpc)

) Each thread uses transitions (I) to move to its first instruction. The remainder of the transitions in Δ are: (

(task, inpc), (t, L1)

(task, inpc), (0, L7)·(t, L2)

)   (1) (

(task, inpc), (t, L7)

,

(0, inpc), ε

)   (2) (

(task, inpc), (t, L7)

,

(1, inpc), ε

)   (3) (

(task, inpc), (t, L8)

,

(

task, inpc), ε

)   (4) The transitions in Δ_(F) are: (

tid, (task, L0), (t, L2)

,

(task, L8), (tid, L3)

)   (1) The transitions in Δ_(J) are: (

t, (task, inpc), (t, L3)

,

(task, inpc), (t, L1)

)   (1)

Example 26 Exemplary Assumptions

In concurrent programs with fork-join parallelism, the usage of thread identifiers (and consequently variables containing thread identifiers) is generally restricted. A thread identifier is generally created by a fork operation and stored in a variable. Then, it may be copied from one variable to another. Finally, a join operation may look at a thread identifier contained in such a variable. Usually, no control flow other than that implicit in a join operation depends on thread identifiers. The restricted use of thread identifiers in concurrent systems can be exploited to allow for one to devise an algorithm for solving the k-bounded reachability problem.

First, the assumptions about the restricted use of thread identifiers are formalized. A renaming function is a partial function from Tid to Tid. When a renaming function ƒ is applied to a global store g, it returns another store in which the value of each variable of type Tid is transformed by an application of ƒ. If ƒ is undefined on the value of some global variable in g, it is also undefined on g. Similarly, a renaming function can be applied to a local store as well. A renaming function is extended to a sequence of local stores by pointwise application to each element of the sequence. Assumptions about the transition relations Δ, Δ_(F), and Δ_(J) are now formalized.

-   -   A1. For all gεG, γεΓ, and renaming functions ƒ such that ƒ(g)         and ƒ(γ) are defined, the following statements are true.         -   1. If (             g, γ             ,             g′, w             )εΔ then there exist ƒg′εG and ƒwεΓ* such that ƒg′=ƒ(g′),             ƒw=ƒ(w), and (             ƒ(g), ƒ(γ)             ,             ƒg′, ƒw             )εΔ.

2. If (

ƒ(g), ƒ(γ)

,

ƒg′, ƒw

)εΔ then there exist g′εG and wεΓ* such that ƒg′=ƒ(g′), ƒw=ƒ(w), and (

g, γ

,

g′, w

)εΔ. TABLE 8 Pictorial View of Assumption A1 $\begin{matrix} \left\langle {g,\gamma} \right\rangle & \overset{\quad\Delta\quad}{\rightarrow} & \left\langle {g^{\prime},w} \right\rangle \\ \left. \downarrow f \right. & \quad & \left. \downarrow f \right. \\ \left\langle {{f(g)},{f(\gamma)}} \right\rangle & \overset{\quad\Delta\quad}{\rightarrow} & \left\langle {{fg}^{\prime},{fw}} \right\rangle \end{matrix}\quad$

Table 8 presents a pictorial view of assumption A1. This view shows four arrows, two horizontal labeled with the transition relation A and two vertical labeled with the renaming function ƒ. The assumption expresses a requirement on tuples (g, γ) for which the left vertical arrow holds. A1.1 states that if the top horizontal arrow holds in addition, then the remaining two arrows hold. Conversely, A1.2 states that if the bottom horizontal arrow holds in addition, then the remaining two arrows hold. The transition relation Δ can be seen to satisfy A1 by the verification of it on each transition (I) and (1)-(4) separately.

-   -   A2. For all tεTid, gεG, γεΓ, and renaming functions ƒ such that         ƒ(t), ƒ(g), and ƒ(γ) are defined, the following statements are         true.         -   1. If (t,             g, γ             ,             g′, w             )εΔ_(F) then there exist ƒg′εG and ƒwεΓ* such that             ƒg′=ƒ(g′), ƒw=ƒ(w), and (ƒ(t),             ƒ(g), ƒ(γ)             .             ƒg′, ƒw             )εΔ_(F).         -   2. If (ƒ(t), (ƒ(t),             ƒ(g), ƒ(γ)             .             ƒg′, ƒw             )εΔ_(F) then there were g′εG and wεΓ* such that ƒg′=ƒ(g′),             ƒw=ƒ(w), and (t,             g, γ             ,             g′, w             )εΔ_(F).     -   A3. For all xεLTV, gεG, γεΓ, and renaming functions ƒ such that         ƒ(g) and ƒ(γ) are defined, the following statements are true.         -   1. If (x,             g, γ             ,             g′, w             )εΔ_(J) then there exist ƒg′εG and ƒwεΓ* such that             ƒg′=ƒ(g′), ƒw=ƒ(w), and (x,             ƒ(g), ƒ(γ)             .             ƒg′, ƒw             )εΔ_(J).         -   2. If (x,             ƒ(g), ƒ(γ)             .             ƒg′, ƒw             )εΔ_(J) then there exist g′εG and wεΓ* such that ƒg′=ƒ(g′),             ƒw=ƒ(w), and (x,             g, γ             ,             g′, w             )εΔ_(J).

Assumption A2 about Δ_(F) and A3 about Δ_(J) are similar in spirit to Δ.

Example 27 Exemplary Reduction to Concurrent Pushdown Systems

In the example, how to reduce the problem of k-bounded reachability on a dynamic concurrent pushdown system to a concurrent pushdown system with k+1 threads is shown. Given a dynamic concurrent pushdown system P and a positive integer k, a concurrent pushdown system P_(k) is produced, containing k+1 threads with identifiers in {0, 1 . . . , k} such that it suffices to verify the k-bounded executions of P_(k).

An insight this approach is that in a k-bounded execution, at most k different threads may perform a transition. It is desirable to simulate transitions of these k threads with transitions of threads in P_(k) with identifiers in {0, . . . , k−1}. The last thread in P_(k) with identifier k never performs a transition; it exists only to simulate the presence of the remaining threads in P.

Let Tid_(k),={0, . . . , k} be the set of the thread identifiers bounded by k. Let AbsG_(k) and AbsΓ_(k) be the set of all valuations to global and local variables respectively, where the variables containing thread identifiers only take values from Tid_(k). Note that both AbsG_(k)p and AbsΓ_(k) are finite sets.

Given a dynamic concurrent pushdown system P=(GBV, GTV, LBV, LTV, Δ, Δ_(F), Δ_(J), g_(in), γ_(in)) and a positive integer k, a concurrent pushdown system is defined: P_(k)=((AbsG_(k)×Tid_(k)×P(Tid_(k),)), (AbsΓ_(k)∪{$}), Δ₀, Δ₁, . . . , Δ_(k), (g_(in), 0, 0), γ_(in)$).

The concurrent pushdown system P_(k) has k+1 threads. A global state of P_(k) is 3-tuple (g, n, α), where g is a valuation to the global variables, n is the largest thread identifier whose corresponding thread is allowed to make a transition, and α is the set of thread identifiers whose corresponding threads have terminated. The initial global state is (g_(in), 0, 0), which indicates that initially only thread 0 can perform a transition and no thread has finished execution. The rules in Table 9 define the transitions in the transition relation Δ_(t) of thread. TABLE 9 Definition of Δ (ABSSEQ) $\frac{t \leq {n\quad\left( {\left\langle {g,\gamma} \right\rangle,\left\langle {g^{\prime},w} \right\rangle} \right)\quad\varepsilon\quad\Delta}}{\left( {\left\langle {\left( {g,n,\alpha} \right),\gamma} \right\rangle,\left\langle {\left( {g^{\prime},n,\alpha} \right),w} \right\rangle} \right)\quad\varepsilon\quad\Delta_{t}}$ (ABSSEQEND) $\frac{t \leq n}{\left( {\left\langle {\left( {g,n,\alpha} \right),\$} \right\rangle,\left\langle {\left( {g,n,{\alpha\bigcup\left\{ t \right\}}} \right),\varepsilon} \right\rangle} \right)\quad\varepsilon\quad\Delta_{t}}$ (ABSFORK) $\frac{t \leq {{n\quad n} + 1} < {k\quad\left( {{n + 1},\left\langle {g,\gamma} \right\rangle,\left\langle {g^{\prime\quad},w} \right\rangle} \right)\quad\varepsilon\quad\Delta_{F}}}{\left( {\left\langle {\left( {g,n,\alpha} \right\rangle\quad,\gamma} \right\rangle,\quad\left\langle {\left( {g^{\prime},{n + 1},\alpha} \right),w} \right\rangle} \right)\quad\varepsilon\quad\Delta_{t}}$ (ABSFORKNONDET) $\frac{t \leq {n\quad\left( {k,\left\langle {g,\gamma} \right\rangle,\left\langle {g^{\prime},w} \right\rangle} \right)\quad\varepsilon\quad\Delta_{F}}}{\left( {\left\langle {\left( {g,n,\alpha} \right),\gamma} \right\rangle,\left\langle {\left( {g^{\prime},n,\alpha} \right),w} \right\rangle} \right)\quad\varepsilon\quad\Delta_{t}}$ (ABSJOIN) $\frac{\begin{matrix} {t \leq {n\quad x\quad\varepsilon\quad{LTV}\quad\left( {x,\left\langle {g,\gamma} \right\rangle,\left\langle {g^{\prime},w} \right\rangle} \right)\quad\varepsilon\quad\Delta_{J}}} \\ {\quad{{\gamma(x)}\quad\varepsilon\quad\alpha}} \end{matrix}}{\left( {\left\langle {\left( {g,n,\alpha} \right),\gamma} \right\rangle,\left\langle {\left( {g^{\prime},n,\alpha} \right),w} \right\rangle} \right)\quad\varepsilon\quad\Delta_{t}}$

The rules in Table 9 are guarded by the condition t≦n to indicate that no transition in thread t is enabled in

(g, n, α), γ

if t>n. The rule (ABSSEQ) adds transitions in Δ to Δ_(t). The rule (ABSSEQEND) adds thread t to the set of terminated threads. The rules (ABSFORK) and (ABSFORKNONDET) handle thread creation in P and are the most crucial part of our transformation. The rule (ABSFORK) handles the case when the new thread being forked participates in a k-bounded execution. This rule increments the counter n allowing thread n+1 to begin simulating the newly forked thread. The rule (ABSFORKNONDET) handles the case when the new thread being forked does not participate in a k-bounded execution. This rule leaves the counter n unchanged thus conserving the precious resource of thread identifiers in P_(k). Both these rules add the transitions of the forking thread in Δ_(F) to Δ. Finally, the rule (ABSJOIN) handles the join operator by using the fact that the identifiers of all previously terminated threads are present in α. Again, this rule adds the transitions of the joining thread in Δ_(J) to Δ.

The correctness theorems for the transformation can now be stated. To simplify the notation required to state these theorems, a configuration

(g′, n′, α), γ), w₀, w₁, . . . , w_(k)

of P_(k) as

(g′, n′, α), ss′

is written, where ss′ is a map from Tid_(k) to (AbsΓ_(k)∪$)*.

First, the transformation is sound, which means that by verifying P_(k), one does not miss erroneous bounded executions of P.

-   -   Theorem 5 (Soundness): Let P be a dynamic concurrent pushdown         system and k be a positive integer. Let (g, n, ss) be a         k-reachable configuration of P. Then there is a total renaming         function ƒ: Tid→Tid_(k) and a k-reachable configuration         (g′, n′, α), ss′         of the concurrent pushdown system P_(k) such that g′=ƒ(g) and         ss′(ƒ(j))=ƒ(ss(j)) for all jεTid.

Second, the transformation is precise, which means that every erroneous k-bounded execution of P_(k) corresponds to an erroneous execution of P.

-   -   Theorem 6 (Completeness): Let P be a dynamic concurrent pushdown         system and k be a positive integer. Let         (g′, n′, α), ss′         be a k-reachable configuration of the concurrent pushdown system         P_(k). Then there is a total renaming function ƒ: Tid→Tid_(k)         and a k-reachable configuration         g, n, ss         of P such that g′=ƒ(g) and ss′(ƒ(j))=ƒ(ss(j)) for all jεTid.

Thus, with Theorem 5 and Theorem 6, the problem of k-bounded reachability on a dynamic concurrent pushdown system to a concurrent pushdown system with k+1 threads has been implemented.

Example 28 Exemplary Proof of Theorem 2

Lemma 1 Suppose that

g, w₀, . . . , w_(i), . . . , w_(N)

→*_(i)

g′, w₀, . . . , w′_(i), . . . , w_(N)

with

g, w_(i)

ε

g, R_(i)

. Then there exists R′such that

g′, R′^(i)

εPost*_(Δ) _(i) (

g, R_(i)

) and

g′, w′_(i)

ε

g′, R′_(i)

.

-   -   PROOF The assumption implies that         g,w_(i)         →*_(Δ) _(i)         g′,w′_(i)         hence         g′,w′_(i)         εPost*_(Δ) _(i) (         g,R_(i)         )   (2)

Writing Post*_(Δ) _(i) (

g′, R_(i)

) on the form (1) provides ${{Post}_{\Delta_{i}}^{*}\left( \left\langle \left\langle {g,R_{i}} \right\rangle \right\rangle \right)} = {\underset{j = 1}{\overset{m}{\uplus}}\left\langle \left\langle {g_{j}^{\prime},R_{j}^{\prime}} \right\rangle \right\rangle}$ for some R′_(i), . . . R′_(m), where G={g₁, . . . g_(m)}. Since g′=g_(j) for some jε{1, . . . , m}, it follows from (2) that (g′, w′_(i))ε(

g_(j), R′_(i)

), and one can chose R′=R′_(j).

Lemma 2 Suppose that

-   -   Then         g, {w₀}, . . . , {w_(N)}         g′, R′₀, . . . , R′_(N)         for some R′₀, . . . , R′_(N) such that w′_(i)εR′_(i) for all         iε{0, . . . , N}.     -   PROOF By induction on k≧1. For k=1, the assumption is that         g, w₀, . . . w_(N)         →*_(i)         g′, w₀, . . . w_(N)         for some iε{0, . . . , N}, i.e.,         g, w₀, . . . , w_(i), . . . , w_(N)         →*_(i)         g′, w₀, . . . , w′_(i), . . . , w_(N)

Since

g, w_(i)

ε

g, {w_(i)}

, Lemma 1 implies that

g′, w′_(i)

ε

g′, R′

for some R′ such that

g′, R′

εPost*_(Δ) _(i) (

g, {w_(i)}

). By the definition of

this shows that

g, {w₀}, . . . , {w_(i)}, . . . , {w_(N)}

g, {w₀}, . . . , R′, . . . , {w_(N)}

which proves the lemma in the base case. For the inductive case, assume

g,w₀, . . . ,w_(i), . . . ,w_(N)

→^([k+1])

g″,w″₀, . . . ,w″_(i), . . . ,w″_(N)

by the relations

g,w₀, . . . ,w_(i), . . . ,w_(N)

→^([k]g′,w) _(0′), . . . ,w′_(i), . . . ,w′_(N)

  (3) and

g′,w′₀, . . . ,w′_(i), . . . ,w′_(N)

→*_(i g″,w′) ₀, . . . ,w″_(i), . . . ,w′_(N)

  (4) By induction hypothesis and (3), one has

g,{w₀}, . . . ,{w_(i)}, . . . ,{w_(N)}

g′,R′₀, . . . ,R′_(i), . . . ,R′_(N)

  (5) for some R′₀, . . . , R′_(N) such that w′_(j)εR′_(j) for all jε{0, . . . , N}. Since one has

g′, w′_(i)

→*_(Δ) _(i)

g″, w″_(i)

by (4) and w′_(i)εR′_(i), it follows that

g′, w′_(i)

ε

g′, R′_(i)

. Lemma 1 then shows that one has

g″, w″_(i)

ε

g″, R″_(i)

for some R″_(i) such that

g″, R″_(i)

εPost*_(Δ) _(i) (

g′, R′_(i)

). It follows that one has

g′,R′₀, . . . ,R′_(i), . . . ,R′_(N)

  (6) Composing (5) and (6) yields

g, {w₀}, . . . , {w_(i)}, . . . , {w_(N)}

thereby proving the lemma in the inductive case.

Lemma 3 Suppose that

g, R₀, . . . , R_(i), . . . , R_(N)

g′, R₀, . . . , R′_(i), . . . , R_(N)

-   -   Then, for all w′_(i)εR′_(i) there exists w_(i)εR_(i) such that         g, w₀, . . . , w_(i), . . . , w_(N)         →*_(i)         g′, w₀, . . . , w′_(i), . . . w_(N)         for all w_(j)εR_(j), jε{0, . . . i+1, . . . N}.     -   PROOF By the assumption one has         g′, R′         εPost*_(Δ) _(i) (         g, R_(i)         )         Hence, one can write         g′, R′_(i)         ={         g′, w′_(i)         |∃         g, w_(i)         ε         g, R_(i)         .         g, w_(i)         →*_(Δ) _(i)         g′, w′_(i)         }         which shows that, for all w′_(i)εR′_(i), there exists w_(i) such         that         g, w_(i)         →*_(Δ) _(i)         g′, w′_(i)         The lemma now follows from the definition of the transition         relation →*_(i).

Lemma 4 Let strings w₀, . . . , w_(N) and w′₀, . . . , w′_(N) be given. Assume that

g, {w₀}, . . . , {w_(i)}, . . . , {w_(N)}

g, R₀, . . . , R_(N)

for some R′₀, . . . , R′_(N) such that w′_(i)εR′_(i) for all iε{0, . . . , N}. Then

-   -   PROOF By induction on k≧1. For the base case, k=1, the         assumption yields:         g, {w₀}, . . . , {w_(i)}, . . . , {w_(N)}         g′, {w₀}, . . . , R′_(i), . . . , {w_(N)}         for some i and R′_(i) with w′_(i)εR′_(i). Then, by Lemma 3,         there exists w″_(i)ε{w_(i)} such that         g, w₁, . . . , w″_(i), . . . , w_(N)         →*_(i)         g, w₁, . . . , w′_(i), . . . , w_(N)         holds. Since one must have w″_(i)=w_(i) by the choice of w″_(i),         the lemma follows.         For the inductive case, assume         g, {w₀}, . . . , {w_(N)}         g′, R′₀, . . . , R′_(N)         with w′_(i)εR′_(i) for all iε{0, . . . , N}. Then, for some         jε{0, . . . , N} and g″, one has         g,{w₀}, . . . ,{w_(N)}         g″,R′₀, . . . ,R″_(j), . . . ,R′_(N)           (7)         and, for some jε{0, . . . N} and R″, one has         g″,R′₀, . . . ,R′_(j−1),R″,R′_(j+1) . . . ,R′_(N)         g′,R′₀, . . . ,R′_(j−1),R′_(j),R′_(j+1), . . . ,R′_(N)           (8)         By induction hypothesis and (7) one has

for all w″εR″. Lemma 3 applied to (8) implies that, for all w″_(j)εR″_(j) there exists w′″εR″ such that

g″,w′₀, . . . ,w′_(j−1),w′″,w′_(j+1), . . . ,w′_(N)

→*_(j g′,w′) ₀, . . . ,w′_(j−1),w′_(j),w′_(j+1), . . . ,w′_(N)

  (10)

holds for all w′_(i)εR′_(i) for iε{0, . . . j−1, j+1, . . . , N}. Because (9) holds for all w″εR″, it holds for w′″ in particular. Hence, composing (9) and (10) proves the lemma.

Theorem 2 Let a concurrent pushdown system P=(G, Γ, Δ₀, . . . , Δ_(N),

g_(in), w_(in)

) be given. Then, for any k,

g, w₀, . . . , w_(N)

g′, w′₀, . . . , w′₀

if and only if

g, {w₀}, . . . , {w_(N)}

g′, R′₀, . . . , R′_(N)

for some R′₀, . . . , R′_(N) such that w′_(i)εR′_(i) for all iε{0, . . . , N}.

-   -   PROOF The theorem follows directly from Lemma 2 and Lemma 4.

Example 29 Exemplary Proofs of Theorem 5 and Theorem 6

A dynamic concurrent pushdown system P, a positive integer k, and the concurrent pushdown system P_(k) are fixed. Each configuration (g, n, ss) of P is augmented to (c, g, n, ss), where c is a subset of Tid. This subset predicts at the beginning of an execution the identifie

the threads that may perform a transiti

any point in the execution. It is initialized non-deterministically and remains unchanged throughout the execution of the system. The transition relation is extended in the obvious way so that if (c, g, n, ss) (c, g′, n′, ss′) then tεc. Every execution over the original configurations can be matched by an execution over the augmented configurations by choosing an appropriate initial value of c. In addition, for every k-bounded execution, a choice of c can be made such that 0εc and |c|≦k. Henceforth, it is assumed that the set c in the augmented configurations of k-bounded execution sequences satisfies the above property.

-   -   Lemma 5 For every reachable configuration         c, g, n, ss         of P, we have ss(t)=γ₀$ for all tεTid such that t>n.         -   PROOF The proof is by induction on the length of the             execution sequence leading to             c, g, n, ss             .     -   Lemma 6 For every reachable configuration         (g, n, α), ss         of P_(k), we have ss(t)=γ₀$ for all tεTid_(k) such that t>n.         -   PROOF The proof is by induction on the length of the             execution sequence leading to             (g, n, α), ss             .     -   Lemma 7 For every reachable configuration         (g, n, α), ss         of P_(k), we have tεα iff ss(t)=ε for all tεTid_(k).         -   PROOF The proof is by induction on the length of the             execution sequence leading to             (g, n, α), ss             .     -   Lemma 8 For every k-bounded execution         c,         ss₀         c, g_(l), n         c, g_(l), n_(l), ss_(l)         of P, there is a renaming function ƒ: Tid→Tid_(k) and an         execution         (g′₀, n′₀, α₀), ss′₀         →_(t′) ₁         (g′₁, n′₁, α₁), ss′₁         →t′ ₂ . . . →_(t′) ₁         (g′_(l), n′_(l), α_(l)), ss′_(l)         of P_(k) such that the following statements are true:         -   1. dom(ƒ)={tεTid|0≦t≦n_(l)}.         -   2. The function ƒ maps dom(ƒ)∩c one-one onto             {tεTid|0≦t≦n′_(l)} and dom(ƒ)\c to k.         -   3. g′_(l)=ƒ(g_(l))         -   4. For all tεdom(ƒ), ss′_(l)(ƒ(t))=ƒ(ss_(l)(t)).         -   PROOF The proof is done by induction over the length l of             the k-bounded execution sequence of the dynamic concurrent             pushdown system.             Base case (l=0): Let ƒ be such that ƒ(0)=0 and ƒ is             undefined elsewhere. It is known that n₀₌0 and n′₀.             Therefore dom(ƒ)={tεTid|0≦t≦n_(l)} and ƒ maps dom(ƒ) one-one             onto {tεTid|0≦t≦n′_(l)}. From the property of g₀, we get             that g′₀=ƒ(g₀)=g₀. From the property of γ₀, one can get that             γ′₀=ƒ(γ₀)=γ₀. Therefore ss′₀(ƒ(0))=ss′₀(0)=γ₀$=ss₀(0).             Inductive case: It is assumed that the theorem holds for l             with a renaming function ƒ. One can now prove the theorem             for l+1 by a case analysis.             (SEQ): One has             c, g_(l), n_(l), ss_(l)             c, g_(l+1), n_(l), ss_(l)[t_(l+1):=ww′]             , where t_(l+1)εc, t_(l+1)≦n_(l), ss_(l)(t_(l+1))=γw′, and (             g_(l), γ             ,             g_(l+1), w             )εΔ. By the induction hypothesis, one has             dom(ƒ)={tεTid|0≦t≦n_(l)}. Therefore t_(l+1)εdom(ƒ)∩c and by             the induction hypothesis, we get ƒ(t_(l+1))≦n′_(l). Let             t′_(l+1)=ƒ(t_(l+1)). By Assumption A1.1, one has (             ƒ(g_(l)), ƒ(γ)             ,             ƒ(g_(l+1)), ƒ(w)             )εΔ. By rule (ABSSEQ), one gets (             (ƒ(g_(l)), n′_(l), α_(l)), ƒ(γ)             ,             (ƒ(g_(l+1)), n′_(l), α_(l)), ƒ(w)             )εΔ_(t′) _(l+1). By the induction hypothesis, one has             ss′_(l)(t′_(l+1))=ƒ(ss_(l)(t_(l+1)))=ƒ(γ)ƒ(w′). Therefore,             one has             (ƒ(g_(l)), n′_(l), α_(l)), ss′_(l)             →_(t′) _(l+1)             (ƒ(g_(l+1)), n′_(l), α_(l)), ss′_(l)[t′_(l+1):=ƒ(w)ƒ(w′)]             .             (SEQEND): One has             c, g_(l), n_(l), ss_(l)             c, g_(l), n_(l), ss_(l)[t_(l+1):=ε]             , where t_(l+1)εc, t_(l+1)≦n_(l) and ss_(l)(t_(l+1))=$. By             the induction hypothesis, one has dom(ƒ)={tεTid|0≦t≦n_(l)}.             Therefore t_(l+1)εdom(ƒ)∩c and by the induction hypothesis,             one gets ƒ(t_(l+1))≦n′_(l). Let t′_(l+1)=ƒ(t_(l+1)). By rule             (ABSSEQEND) one gets (             (g_(l), n′_(l), α_(l)), $             ,             (g_(l), n′_(l), α_(l)∪{t′_(l+1)}), ε             )εΔ_(t′) _(l+1). By the induction hypothesis, one has             ss′_(l)(t′_(l+1))=ƒ(ss_(l)(t_(l+1)))=ƒ($)=$. Therefore, one             has             (g_(l), n′_(l), α_(l))ss′_(l)             →_(t′) _(l+1)             (g_(l), n′_(l), α_(l)∪{t′_(l+1)}), ss′_(l)[t_(l+1):=ε]             .             (FORK): We have             c, g_(l), n_(l), ss_(l)             c, g_(l+1), n_(l)+1, ss_(l)[t_(l+1):=ww′]             , where t_(l+1)εc, t_(l+1)≦n_(l), ss_(l)(t_(l+1))=γw′, and             (n_(l)+1,             g_(l), γ             ,             g_(l+1), w             )εΔ_(F). By the induction hypothesis, one has             dom(ƒ)={tεTid|0≦t≦n_(l)}. Therefore, t_(l+1)εdom(ƒ)∩c and by             the induction hypothesis, one gets ƒ(t_(l+1))≦n′_(l). Let             t′_(l+1)=ƒ(t_(l+1)). There are two cases:

1. (n_(l)+1εc): Since |c|≦k, n_(l)+1εdom(ƒ), and n_(l)+1εc, one has |dom(ƒ)∩c|<k. Therefore |{tεTid|0≦t≦n′_(l)}|=dom(ƒ)∩c|<k, which implies that n′_(l)+1<k. One can extend the renaming function ƒ so that ƒ(n_(l)+1)=n′_(l)+1. By Assumption A2.1, one has (n′_(l)+1,

ƒ(g_(l)), ƒ(γ)

,

ƒ(g_(l+1)), ƒ(w)

)εΔ_(F). By rule (ABSFORK), one gets (

(ƒ(g_(l)), n′_(l), α_(l)), ƒ(γ)

,

(ƒ(g_(l+1)), n′_(l)+1, α_(l)), ƒ(w)

)εΔ_(t′) _(l+1). By the induction hypothesis, one has ss′_(l)(t′_(l+1))=ƒ(ss_(l)(t_(l+1)))=ƒ(γ)=ƒ(γ)=ƒ(w′). From Lemmas 5 and 6 and the property of γ₀, one gets that ss′_(l)(ƒ(n+1))=ƒss′_(l)(n′+1))=γ₀$=ƒ(γ₀$)=ƒ(ss_(l)(n_(l)1)). Therefore, one has

(ƒ(g_(l)), n′_(l), α_(l)), ss′_(l)

→_(t′) _(l+1)

(ƒ(g_(l+1)), n′_(l)1, α_(l)), ss′_(l)[t′_(l+1):=ƒ(w)ƒ(w′)]

.

2. (n_(l)+1∉c): One can extend the remaining function ƒ so that ƒ(n_(l)+1)=k. By Assumption, A2.1, one has (k,

ƒ(g_(l)), ƒ(γ)

,

ƒ(g_(l+1)), ƒ(w)

)εΔ_(F). By the rule (ABSFORKNONDET), one gets (

(ƒ(g_(l)), n′_(l), α_(l)), ƒ(γ)

,

(ƒ(g_(l+1)), n′_(l), α_(l))ƒ(w)

)εΔ_(t′) _(l+1). By the induction hypothesis, one has ss′_(l)(t′_(l+1))=ƒ(ss_(l)(t_(l+1)))=ƒ(γ)=ƒ(w′). From Lemmas 5 and 6 and the property of γ₀, one gets that ss′_(l)(ƒ(n+1))=ss′_(l)(k)=γ₀$=ƒ(γ₀$)=ƒ(ss_(l)(n+1)). Therefore, one has

(ƒ(g_(l)), n′_(l), α_(l)), ss′_(l)

→_(t′) _(l+1)

(ƒ(g_(l+1)), n′_(l)1, α_(l)), ss′_(l)[t′_(l+1):=ƒ(w)ƒ(w′)]

.

(JOIN) One has

c, g_(l), n_(l), ss_(l)

c, g_(l+1), n_(l), ss_(l)[t_(l+1):=ww′]

, where t_(l+1)εc, t_(l+1)≦n_(l), ss_(l)(t_(l+1))=γw′, (x,

g_(l), γ

,

g_(l+1), w

)εΔ for some xεLTV, and ss_(l)(γ(x))=ε. By the induction hypothesis, one has dom(ƒ)={tεTid|0≦t≦n_(l)}. Therefore t_(l+1)εdom(ƒ)∩c and by the induction hypothesis, one gets ƒ(t_(l+1))≦n′_(l). Let t′_(l+1)ƒ(t_(l+1)). By Assumption A3.1, one has (x,

ƒ(g_(l)), ƒ(γ)

,

ƒ(g_(l+1)), ƒ(2)

)εΔ_(F). By the induction hypothesis, one has ss′_(l)(ƒ(γ)(x))=ss′_(l)(ƒ(γ(x)))=ƒ(ss_(l)(γ(x)))=ƒ(ε). From Lemma 7, one gets ƒ(γ)(x)εα_(l). By rule (ABSJOIN), one gets (

(ƒ(g_(l)), n′_(l), α_(l)), ƒ(γ)

,

(ƒ(g_(l+1)), n′_(l), α_(l)), ƒ(w)

)εΔ_(t′) _(l+1). By the induction hypothesis, one has ss′_(l)(t′_(l+1))=ƒ(ss_(l)(t_(l+1)))=ƒ(γ)ƒ(w′). Therefore, one has

(ƒ(g_(l)), n′_(l), α_(l)), ss′_(l)

→_(t′) _(l+1)

(ƒ(g_(l+1)), n′_(l), α_(l)), ss′_(l)[t′_(l+1):=ƒ(w)ƒ(w′)]

.

Theorem 5 Let P be a dynamic concurrent pushdown system and k be a positive integer. Let (g, n, ss) be a k-reachable configuration of P. Then there is a total renaming function ƒ: Tid→Tid_(k) and a k-reachable configuration

(g′, a′, a), ss′

of the concurrent pushdown system P_(k), such that g′=ƒ(g) and ss′(ƒ(j))=ƒ(ss(j)) for all jεTid.

PROOF The proof follows immediately from Lemma 8.

-   -   Lemma 9 For every k-bounded execution         (g′₀, n′₀, α₀), ss′₀         →_(t′) _(l)         (g′₁, n′₁, α₁), ss′₁         →_(t′) ₂ . . . →_(t′) _(l)         (g′_(l), n′_(l), α_(l)), ss′_(l)         of P_(k), there is a renaming function ƒ: Tid→Tid_(k), and an ex         ion         g₀, n₀, ss₀         n_(l), ss_(l)         , . . .         g_(l), n_(l), ss_(l)         of P such that the following statements are true.         -   1. dom(ƒ)={tεTid|0≦t≦n_(l)}.         -   2. ƒ maps dom(ƒ)\{tεTid|ƒ(t)=k} one-one onto             {tεTid|0≦t≦n′_(l)}.         -   3. g′_(l)=ƒ(g_(l)).         -   4. For all tεdom(ƒ), ss′_(l)(ƒ(t))=ƒ(ss_(l)(t)).         -   PROOF The proof can be done by induction over the length l             of the k-bounded execution sequence of the dynamic             concurrent pushdown system.             Base case (l=0): Let ƒ be such that ƒ(0)=0 and ƒ is             undefined elsewhere. It is known that n′₀=0 and n₀=0.             Therefore dom(ƒ)={tεTid|0≦t≦n_(l)}and ƒ maps dom(ƒ) one-one             onto {tεTid|0≦t≦n′_(l)}. From the property of g₀, we get             that g′₀=ƒ(g₀)=g₀. From the property of γ₀, one gets that             γ′₀=ƒ(γ₀)=γ₀. Therefore ss′₀(ƒ(0))=ss′₀(0)=γ₀$=ss₀(0).             Inductive case: It is assumed that the theorem holds for l             with a renaming function ƒ. One can now prove the theorem             for l+1 by a case analysis.             (ABSSEQ): One has             (g′_(l), n′_(l), α_(l)), ss′_(l)             →_(t′) _(l+1)             (g′_(l+1), n′_(l), α_(l)), ss′_(l)             , where 0≦t′_(l+1)≦n′_(l). By the induction hypothesis, one             has dom(ƒ)={tεTid|0≦t≦n_(l)} and there is t_(l+1)εdom(ƒ)             such that t′_(l+1)=ƒ(t_(l+1)). Let ss_(l)(t_(l+1))=γw′. By             the induction hypothesis, one has             ss′_(l)(t′_(l+1))=ƒ(ss_(l)(t_(l+1)))=ƒ(γ)ƒ(w′) and             g′_(l)=ƒ(g_(l)). Let ss′_(l)(t′_(l+1))=w′_(l+1)ƒ(w′). Then (             ƒ(g_(l)), ƒ(γ)             ,             g′_(l+1), w′_(l+1)             )εΔ. By Assumption A1.2, there exist g_(l+1) and w_(l+1)             such that g′_(l+1)=ƒ(g_(l+1)), w′_(l+1)=ƒ(w_(l+1)), and (             g_(l), γ             ,             g_(l+1), w_(l+1)             )εΔ. By rule (SEQ), one gets             g_(l), n_(l), ss_(l)             g_(l+1), n_(l), ss_(l)[t_(l+1):=w_(l+1) w′]             .             (ABSSEQEND): One has             (g′_(l), n′_(l), α_(l)), ss′_(l)             →_(t′) _(l+1)             (g′_(l), n′_(l), α_(l)∪{t′_(l+1)}), ss′_(l)[t′_(l+1):=ε]             , where 0≦t′_(l+1)≦n′_(l) and s′_(l+1)(t′_(l+1))=$. By the             induction hypothesis, one has dom(ƒ)={tεTid|0≦t≦n_(l)} and             there is t_(l+1)εdom(ƒ) such that t′_(l+1)=ƒ(t_(l+1)). By             the induction hypothesis, one has             $=ss′_(l)(t′_(l+1))=ƒ(ss_(l)(t_(l+1))). Therefore             ss_(l)(t_(l+1))=$. By rule (SEQEND), one gets (g_(l), n_(l),             ss_(l)             g_(l), n_(l), ss_(l)[t_(l+1):=ε]             .             (ABSFORK): One has             (g′_(l), n′_(l), α_(l)), ss′_(l)             →_(t′) _(l+1)             (g′_(l), n′_(l)+1, α_(l)), ss′_(l)             , where 0≦t′_(l+1)≦n′_(l) and n′+1<k. By the induction             hypothesis, one has dom(ƒ)={tεTid|0≦t≦n_(l)} and there is             t_(l+1)εdom(ƒ) such that t′_(l+1)=ƒ(t_(l+1)). Let             ss_(l)(t_(l+1))=γw′. By the induction hypothesis, one has             ss′_(l)(t_(l+1))=ƒ(ss_(l)(t_(l+1)))=ƒ(γ)ƒ(w′) and             g′_(l)=ƒ(g_(l)). Let ss′_(l+1)(t′_(l+1))=w′_(l+1)ƒ(w′).             Extend ƒto n_(l)+1 so that ƒ(n_(l)+1)=n′_(l)+1. Then             (ƒ(n_(l)+1),             ƒ(g_(l)), ƒ(γ)             ,             g′_(l+1), w′_(l+1)             ) εΔ_(F). By Assumption A2.2, there exist g_(l+1) and             w_(l+1) such that g′_(l+1)=ƒ(g_(l+1)), w′_(l+1)=ƒ(w_(l+1))             and n_(l)+1,             g_(l), γ             ,             g_(l+1), w_(l+1)             )εΔ_(F). By rule (FORK), we get (g_(l), n_(l), ss_(l))             g_(l+1), n_(l)+1, ss_(l)[t_(l+1):=w_(l+1) w′]             . From Lemmas 5 and 6 and the property of γ₀, one gets that             ss′_(l)(ƒ(n_(l)+1))=ss′_(l)(n_(l)+1)=γ₀$=ƒ(γ₀$)=ƒ(ss_(l)(n_(l)+1)).             (ABSFORKNONDET): One has             (g′_(l), n′_(l), α_(l)), ss′_(l)             →_(t′) _(l+1)             (g′_(l+1), n′_(l)+1, α_(l)), ss′_(l+1)             where 0≦t′_(l+1)≦n′_(l). By the induction hypothesis, one             has dom(ƒ)={tεTid|0≦t≦n_(l)} and there is t_(l+1)εdom(ƒ)             such that t′_(l+1)=ƒ(t_(l+1)). Let ss_(l)(t_(l+1))=γw′. By             the induction hypothesis, one has             ss′_(l)(t_(l+1))=ƒ(ss_(l)(t_(l+1)))=ƒ(γ)ƒ(w′) and             g′_(l)=ƒ(g_(l)). Let ss′_(l)(t′_(l+1))=w′_(l+1)ƒ(w′). Extend             ƒ to n_(l)+1 so that ƒ(n_(l)+1)=k. Then (ƒ(n_(l)+1),             ƒ(g_(l)), ƒ(γ)             ,             g′_(l+1), w′_(l+1)             )εΔ_(F). By Assumption A2.2, there exist g_(l+1) and w_(l+1)             such that g′_(l+1)=ƒ(g_(l+1)), w′_(l+1)=ƒ(w_(l+1)), and             (n_(l)+1,             g_(l), γ             ,             g_(l+1), w_(l+1)             )εΔ_(F). By rule (FORK), one gets             g_(l), n_(l), ss_(l)             g_(l+1), n_(l)+1, ss_(l)[t_(l+1):=w_(l+1) w′]             . From Lemmas 5 and 6 and the property of γ₀, one gets that             ss′_(l)(ƒ(n_(l)+1))=ss′_(l)(n_(l)+1)=γ₀$=ƒ(γ₀$)=ƒ(ss_(l)(n_(l)+1)).             (ABSJOIN) One has             (g′_(l), n′_(l), α_(l)), ss′_(l)             →_(t′) _(l+1)             (g′_(l+1), n′_(l)+1, α_(l)), ss′_(l)             , where 0≦t′_(l+1)≦n′_(l). By the induction hypothesis, one             has dom(ƒ)={tεTid|0≦t≦n_(l)} and there is t_(l+1)εdom(ƒ)             such that t′_(l+1)=ƒ(t_(l+1)). Let ss_(l)(t_(l+1))=γw′. By             the induction hypothesis, one has             ss′_(l)(t′_(l+1))=ƒ(ss_(l)(t_(l+1)))=ƒ(γ)ƒ(w′) and             g′_(l)=ƒ(g_(l)). Let ss′_(l+1)(t′_(l+1))=w′_(l+1)ƒ(w′). Then             there is xεLTV such that (x,             ƒ(g_(l)), ƒ(γ)             , (g′_(l+1), w′_(l+1)))εΔ_(J) and ƒ(γ)(x)εα_(l). By             Assumption A3.2, there exist g_(l+1) and w_(l+1) such that             g′_(l+1)=ƒ(g_(l+1)), w′_(l+1)=ƒ(w_(l+1)), and (x,             g_(l) γ             ,             g_(l+1), w_(l+1)             )εΔ_(J). From Lemma 7, one gets ss′_(l)(ƒ(γ)(x))=ε. By the             induction hypothesis, one gets ss_(l)(ƒ(γ)(x))=ε. By rule             (JOIN), one gets             g_(l), n_(l), ss_(l)             g_(l+1), n_(l)+1, ss_(l)[t_(l+1):=w_(l+1) w′]             .

Theorem 6 Let P be a dynamic concurrent pushdown system and k be a positive integer. Let

(g′, n′, α), ss′

be a k-reachable configuration of the concurrent pushdown system P_(k). Then there is a total renaming function ƒ: Tid→Tid_(k) and a k-reachable configuration (g, n, ss) of P such that g′=ƒ(g) and ss′(ƒ(j))=ƒ(ss(j)) for all jεTid.

PROOF The proof follows immediately from Lemma 9.

Example 30 Exemplary Computing Environment

FIG. 9 and the following discussion are intended to provide a brief, general description of an exemplary computing environment in which the disclosed technology may be implemented. Although not required, the disclosed technology will be described in the general context of computer-executable instructions, such as program modules, being executed by a personal computer (PC). Generally, program modules include routines, programs, objects, components, data structures, etc. that perform particular tasks or implement particular abstract data types. Moreover, the disclosed technology may be implemented with other computer system configurations, including hand-held devices, multiprocessor systems, microprocessor-based or programmable consumer electronics, network PCs, minicomputers, mainframe computers, and the like. The disclosed technology may also be practiced in distributed computing environments where tasks are performed by remote processing devices that are linked through a communications network. In a distributed computing environment, program modules may be located in both local and remote memory storage devices.

With reference to FIG. 9, an exemplary system for implementing the disclosed technology includes a general purpose computing device in the form of a conventional PC 900, including a processing unit 902, a system memory 904, and a system bus 906 that couples various system components including the system memory 904 to the processing unit 902. The system bus 906 may be any of several types of bus structures including a memory bus or memory controller, a peripheral bus, and a local bus using any of a variety of bus architectures. The system memory 904 includes read only memory (ROM) 908 and random access memory (RAM) 910. A basic input/output system (BIOS) 912, containing the basic routines that help with the transfer of information between elements within the PC 900, is stored in ROM 908.

The PC 900 further includes a hard disk drive 914 for reading from and writing to a hard disk (not shown), a magnetic disk drive 916 for reading from or writing to a removable magnetic disk 917, and an optical disk drive 918 for reading from or writing to a removable optical disk 919 (such as a CD-ROM or other optical media). The hard disk drive 914, magnetic disk drive 916, and optical disk drive 918 are connected to the system bus 906 by a hard disk drive interface 920, a magnetic disk drive interface 922, and an optical drive interface 924, respectively. The drives and their associated computer-readable media provide nonvolatile storage of computer-readable instructions, data structures, program modules, and other data for the PC 900. Other types of computer-readable media which can store data that is accessible by a PC, such as magnetic cassettes, flash memory cards, digital video disks, CDs, DVDs, RAMs, ROMs, and the like, may also be used in the exemplary operating environment.

A number of program modules may be stored on the hard disk, magnetic disk 917, optical disk 919, ROM 908, or RAM 910, including an operating system 930, one or more application programs 932, other program modules 934, and program data 936. A user may enter commands and information into the PC 900 through input devices such as a keyboard 940 and pointing device 942 (such as a mouse). Other input devices (not shown) may include a digital camera, microphone, joystick, game pad, satellite dish, scanner, or the like. These and other input devices are often connected to the processing unit 902 through a serial port interface 944 that is coupled to the system bus 906, but may be connected by other interfaces such as a parallel port, game port, or universal serial bus (USB). A monitor 946 or other type of display device is also connected to the system bus 906 via an interface, such as a video adapter 948. Other peripheral output devices, such as speakers and printers (not shown), may be included.

The PC 900 may operate in a networked environment using logical connections to one or more remote computers, such as a remote computer 950. The remote computer 950 may be another PC, a server, a router, a network PC, or a peer device or other common network node, and typically includes many or all of the elements described above relative to the PC 900, although only a memory storage device 952 has been illustrated in FIG. 9. The logical connections depicted in FIG. 9 include a local area network (LAN) 954 and a wide area network (WAN) 956. Such networking environments are commonplace in offices, enterprise-wide computer networks, intranets, and the Internet.

When used in a LAN networking environment, the PC 900 is connected to the LAN 954 through a network interface 958. When used in a WAN networking environment, the PC 900 typically includes a modem 960 or other means for establishing communications over the WAN 956, such as the Internet. The modem 960, which may be internal or external, is connected to the system bus 906 via the serial port interface 944. In a networked environment, program modules depicted relative to the personal computer 900, or portions thereof, may be stored in the remote memory storage device. The network connections shown are exemplary, and other means of establishing a communications link between the computers may be used.

ALTERNATIVES

The technologies from any example can be combined with the technologies described in any one or more of the other examples. In view of the many possible embodiments to which the principles of the invention may be applied, it should be recognized that the illustrated embodiments are examples of the invention and should not be taken as a limitation on the scope of the invention. Rather, the scope of the invention includes what is covered by the following claims. We therefore claim as our invention all that comes within the scope and spirit of these claims. 

1. One or more computer-readable media having computer-executable instructions for performing a method comprising: receiving a representation of a plurality of software instructions; determining validity of one or more assertions for any concurrent execution of the plurality of software instructions having at most k−1 context switches.
 2. The one or more computer-readable media of claim 1, wherein the determining validity of the one or more assertions accounts for execution of the software instructions in an unbounded stack depth scenario.
 3. The one or more computer-readable media of claim 1, wherein the representation of the plurality of software instructions comprises a concurrent pushdown system.
 4. The one or more computer-readable media of claim 3, wherein the determining validity of the one or more assertions comprises determining reachability via the concurrent pushdown system.
 5. The one or more computer-readable media of claim 4, wherein the method further comprises: defining a k-bounded transition relation for the concurrent pushdown system.
 6. The one or more computer-readable media of claim 5, wherein the method further comprises; defining at least one aggregate configuration based at least in part upon the k-bounded transition relation.
 7. The one or more computer-readable media of claim 1, wherein the determining comprises: generating a finite representation of an unbounded set of stack configurations.
 8. The one or more computer-readable media of claim 1, wherein: the determining validity of the one or more assertions is performed for at least a first thread executing a first sub-plurality of the plurality of software instructions and a second thread executing a second, separate sub-plurality of the plurality of software instructions, the first thread executing the first sub-plurality of the plurality of software instructions and the second thread executing the second, separate sub-plurality of the plurality of software instructions concurrently.
 9. The one or more computer-readable media of claim 1, wherein the determining validity of the one or more assertions accounts for thread creation during execution of the plurality of software instructions.
 10. The one or more computer-readable media of claim 1, the method further comprising: translating the plurality of software instructions into the representation of the plurality of software instructions.
 11. The one or more computer-readable media of claim 10, wherein the translating comprises: constructing a pushdown system representation of the plurality of software instructions.
 12. The one or more computer-readable media of claim 11, wherein the method further comprises: determining reachability of at least one execution path within the pushdown system.
 13. One or more computer-readable media having computer-executable instructions for performing a method comprising: receiving a plurality of source code software instructions; translating the plurality of source code software instructions into a finite data domain representation of the plurality of source code software instructions; constructing a pushdown system representing the finite data domain representation; and analyzing the pushdown system via a reachability analysis, wherein the reachability analysis analyzes the pushdown system to determine validity of one or more assertions for any concurrent execution of the plurality of source code software instructions with at most k−1 context switches; wherein the analyzing the pushdown system accounts for execution of the plurality of source code software instructions in an unbounded stack depth scenario; and wherein the analyzing the pushdown system accounts for thread creation during execution of the plurality of source code software instructions.
 14. A system comprising: a stored representation of an upper bound; and a model checker operable to check a representation of a plurality of software instructions of a multi-threaded program; wherein the model checker is operable to check validity of one or more assertions for any multi-threaded execution of the multi-threaded program with at most a number of context switches determined based at least in part upon the upper bound.
 15. The system of claim 14, wherein the model checker is operable to determine validity for execution of the multi-threaded program in an unbounded stack scenario.
 16. The system of claim 14, wherein every assertion reported by the model checker as invalid is invalid.
 17. The system of claim 14, wherein every assertion violation that can be manifested with up to k−1 context switches is identified.
 18. The system of claim 14 wherein the model checker accounts for creation of threads during execution of the multi-threaded program.
 19. The system of claim 14, wherein the model checker is operable to perform a reachability analysis for the multi-threaded program.
 20. The system of claim 19 wherein the reachability analysis comprises searching through a plurality of possible execution paths within a pushdown system. 